package com.sinosoft.builder.model;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * Java Class model.<br>
 * Java类对象模型，用于构建java类文件
 * 
 * @author 潘巍（Peter Pan）
 * @since 2010-5-14 下午05:03:22
 */
public class JavaClass extends JavaLanguageElement {
	private List<JavaField> fields = new ArrayList<JavaField>();
	private List<JavaMethod> methods = new ArrayList<JavaMethod>();
	private Set<JavaImport> imports = new TreeSet<JavaImport>(
			new Comparator<JavaImport>() {
				public int compare(JavaImport o1, JavaImport o2) {
					return o1.getName().compareTo(o2.getName());
				}
			});

	private JavaPackage pakg;
	private Class<?> superClass = Object.class;

	public JavaClass(String shortName, JavaPackage pakg, Class<?> superClass) {
		this(shortName, pakg);
		setSuperClass(superClass);
	}

	public JavaClass(String shortName, JavaPackage pakg) {
		super(shortName);
		this.pakg = pakg;
	}

	public void addImport(String name) {
		imports.add(new RuntimeImport(name));
	}

	public void addImport(Class<?> claz) {
		if (shouldAddToImports(claz)) {
			imports.add(new ClassImport(claz));
		}
	}

	@Override
	public void addAnnotation(JavaAnnotation annotation) {
		super.addAnnotation(annotation);
		addImport(annotation.getType());
	}

	public void addField(JavaField field) {
		fields.add(field);
		addImport(field.getType());

		List<JavaAnnotation> annotations2 = field.getAnnotations();
		if (annotations2 != null) {
			for (JavaAnnotation javaAnnotation : annotations2) {
				addImport(javaAnnotation.getType());
			}
		}
	}

	public void addMethod(JavaMethod method) {
		methods.add(method);
		addImport(method.getReturnType());

		List<Class<Throwable>> exceptions = method.getExceptions();

		for (Class<Throwable> exception : exceptions) {
			addImport(exception);
		}

		List<Argument> arguments = method.getArguments();

		if (arguments != null) {
			for (Argument argument : arguments) {
				addImport(argument.getType());
			}
		}

		List<JavaAnnotation> annotations2 = method.getAnnotations();
		if (annotations2 != null) {
			for (JavaAnnotation javaAnnotation : annotations2) {
				addImport(javaAnnotation.getType());
			}
		}

		MethodBody methodBody = method.getMethodBody();
		if (methodBody != null) {
			Set<Class<?>> usedClasses = methodBody.getUsedClasses();
			for (Class<?> class1 : usedClasses) {
				addImport(class1);
			}
		}

	}

	public JavaPackage getPakg() {
		return pakg;
	}

	public Class<?> getSuperClass() {
		return superClass;
	}

	public void setSuperClass(Class<?> superClass) {
		this.superClass = superClass;
		addImport(superClass);
	}

	public void setPackage(JavaPackage s) {
		pakg = s;
	}

	public JavaPackage getPackage() {
		return pakg;
	}

	public List<JavaField> getFields() {
		return fields;
	}

	public List<JavaMethod> getMethods() {
		return methods;
	}

	public Set<JavaImport> getImports() {
		return imports;
	}

	private boolean shouldAddToImports(Class<?> clas) {

		boolean result = false;

		if (clas != null) {
			Package p = clas.getPackage();

			if (!(clas.isPrimitive() || p == null)) {
				String importPackageName = p.getName();
				if (importPackageName != null
						&& importPackageName.length() != 0) {

					result = !(importPackageName.equals("java.lang") || importPackageName
							.equals(getPackage().getName()));
				}
			}
		}

		return result;
	}

}
